package com.zzr.zzrbackend.util;

import com.auth0.jwt.JWT;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.TextCodec;

import java.util.*;

public class TokenUtils {

    //加密算法
    private final static SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;

    //私钥
    private final static String secret = "BUTINGHUADEFAJIXIAN@ZZR";

    // 过期时间（单位秒）/ 24*7小时
    private final static Long access_token_expiration = 604800L;

    //jwt签发者
    private final static String jwt_iss = "ZZR_BACKEND";

    //jwt所有人
    private final static String subject = "ZZR_USER";


    /**
     * 生成Token
     *
     * @return
     */
//    @Deprecated
//    public static String getToken(String userName, String sign) throws NoSuchAlgorithmException {   //以password作为签名
//        String password = MD5Utils.getMD5Str(sign);
//        return JWT.create().withAudience(userName)// 将 user id 保存到 token 里面.作为载荷
//                .withExpiresAt(DateUtil.offsetHour(new Date(), 24 * 7)) //使用huttool里的util设置两小时过期
//                .sign(Algorithm.HMAC256(password)); // 以 password 作为 token 的密钥
//    }

    /**
     * 创建jwt
     *
     * @return 返回生成的jwt token
     */
    public static String generateJwtToken(Map<String, Object> claims) {

        // 头部 map / Jwt的头部承载，第一部分
        // 可不设置 默认格式是{"alg":"HS256"}
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");


        //载荷 map / Jwt的载荷，第二部分
        //标准中注册的声明 (建议但不强制使用)
        //一旦写标准声明赋值之后，就会覆盖了那些标准的声明
        claims.put("iss", jwt_iss);
            /*	iss: jwt签发者
                sub: jwt所面向的用户
                aud: 接收jwt的一方
                exp: jwt的过期时间，这个过期时间必须要大于签发时间
                nbf: 定义在什么时间之前，该jwt都是不可用的.
                iat: jwt的签发时间
                jti: jwt的唯一身份标识，主要用来作为一次性token,从而回避重放攻击
            */


        //下面就是在为payload添加各种标准声明和私有声明了
        return Jwts.builder() // 这里其实就是new一个JwtBuilder，设置jwt的body
                .setHeader(map)         // 头部信息
                .setClaims(claims)      // 载荷信息
                .setId(UUID.randomUUID().toString()) // 设置jti(JWT ID)：是JWT的唯一标识，从而回避重放攻击。
                .setIssuedAt(new Date())       // 设置iat: jwt的签发时间
                .setExpiration(new Date(System.currentTimeMillis() + access_token_expiration * 1000)) // 设置exp：jwt过期时间
                .setSubject(subject)    //设置sub：代表这个jwt所面向的用户，所有人
                .signWith(SIGNATURE_ALGORITHM, TextCodec.BASE64.encode(secret))//设置签名：通过签名算法和秘钥生成签名
                .compact(); // 开始压缩
    }

    @Deprecated
    public static String getUserNameByToken(String token) {
        List<String> userName = null;
        userName = JWT.decode(token).getAudience();
        if (userName.size() == 0) {
            return null;
        }
        return userName.get(0);
    }

    /**
     * 从jwt中获取 载荷 信息
     *
     * @param jwt
     * @return
     */
    public static Claims getClaimsFromJwt(String jwt) {
        Claims claims = null;
        try {
            claims = Jwts.parser().setSigningKey(TextCodec.BASE64.encode(secret)).parseClaimsJws(jwt).getBody();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return claims;
    }

    public static void verify(String token) {
        Jwts.parser()
                .setSigningKey(TextCodec.BASE64.encode(secret))
                .setAllowedClockSkewSeconds(access_token_expiration)
                .parseClaimsJws(token)
                .getBody();
    }


}
